package edu.unc.comp410.colemangeer.model;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;

import org.apache.log4j.Logger;

import edu.unc.comp410.colemangeer.model.constraints.IConstraint;

/**
 * 
 * --- The price of any singleton in the Catalog does not exceed
 * its price in Product.
 * 
 * --- The price of any bundle in the Catalog is always less than
 * the sum of the prices of the components of the bundle. 
 * When several items are bundled together to form a single
 * item in the Catalog, the price of the bundle is always less
 * than the price obtained by purchasing the items individually.
 * 
 * --- A bundle may not contain more than one instance of a
 * Product. For example, with reference to the specific catalog
 * you will set up for your project, it would not be legal to
 * define

    CatalogId = 30, name = Illegal, CompleteMiddleEarth plus
	product 11. 
	
 *	Product 11 (Ring of Power - Elf) is already
 *	a part of the bundle, CompleteMiddleEarth.
 *
 */

public class CatalogItem implements ISellable, IConstraint{

	private static Logger log = Logger.getLogger(CatalogItem.class);
	
	private final Integer Id;
	private final String name;
	private final Double price;
	
	// the products and catalog items for sale
	private List<ISellable>catalogItemDetail;
	
	// The products contained in this CatalogItem - use this?
	//private List<Product> productList;
	
	public List<Product> getProductList() {
		return new ArrayList<Product>();
	}

//	public void setProductList(List<Product> productList) {
//		this.productList = productList;
//	}

	//item categories
	private Set<ProductCategory> categories;
	
	// item discount
	private ItemDiscount itemDiscount;
	
	
	/**
	 * Constructors
	 */

	public CatalogItem(Integer Id, String name, Double price,
			List<ISellable> detail, Set<ProductCategory> categories){
		this.Id = Id;
		this.name = name;
		this.price = price;
		this.catalogItemDetail = detail;
		this.categories = categories;
	}

	// get all and only the actual products
	public List<Product> getAllProducts(){
		ArrayList<Product> products = new ArrayList<Product>();
		
		for (ISellable itemList: catalogItemDetail){
			if (itemList instanceof Product){
				products.add((Product) itemList);
			}
			else{
				products.addAll(itemList.getAllProducts());
			}
			
		}
		return Collections.unmodifiableList(products); 
	}

	//Does this CatalogItem already contain a given product?
	//Needed for legal construction
	public boolean hasProduct(Product product){
		return getAllProducts().contains(product);
	}
	/**
	 * Getters and Setters
	 */
	public Integer getId() {
		return Id;
	}

	public String getName() {
		return name;
	}

	//This is the raw price, before discounts and tax
	public Double getPrice(){
		return price;
	}
	
	//This is the price with item discount, if any exists
	public double getSalePrice() {
		if (itemDiscount == null){
			return getPrice();
		}
		else{
			return itemDiscount.getDiscountedPrice(price);
		}
	}
	
	public double getTaxedSalePrice(ShippingInfo shippingLocale){
		
		if (shippingLocale==null ||
				(shippingLocale.getTaxRegion()==null || shippingLocale.getTaxCountry()==null))
			throw new IllegalArgumentException();
		
		TaxRule taxRule = TaxRule.getTaxRuleForCountry(shippingLocale.getTaxCountry());
		taxRule.setTaxCountry(shippingLocale.getTaxCountry());
		taxRule.setTaxRegion(shippingLocale.getTaxRegion());
		
		return taxRule.computeTaxPrice(getSalePrice(), this.categories);
		
	}
	
	public ItemDiscount getItemDiscount() {
		return itemDiscount;
	}

	public void setItemDiscount(ItemDiscount itemDiscount) {
		this.itemDiscount = itemDiscount;
	}
	
	/**
	 * Setup method for constructors
	 */
	private void initialize(){
		//productList = new ArrayList<Product>();
	}
	
	@Override
	public Object clone() throws CloneNotSupportedException {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public boolean equals(Object obj) {
		if (!(obj instanceof CatalogItem))
			return false;
		CatalogItem compareItem = (CatalogItem) obj;
		
		return this.catalogItemDetail.equals(compareItem.catalogItemDetail);
	}

	@Override
	public int hashCode() {
		return  catalogItemDetail.hashCode();//getProductList().hashCode();
	}

	@Override
	public String toString() {
		//TODO: better toString()
		StringBuilder sb = new StringBuilder();
		sb.append("Catalog Item ").append(getId()).append(" | ").append(getName()).
				append(" | ").append(getPrice());
		return sb.toString();
	}

	@Override
	public String getConstraintName() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public boolean isLegal(Object theObject) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public void validate(Object theObject) throws IllegalStateException {
		// TODO Auto-generated method stub

	}
	
}
